#ifndef GLOBAL_CHN_RECOGNITION_2013_01_03_H
#define GLOBAL_CHN_RECOGNITION_2013_01_03_H

struct SPoint;
class CStrokeDB;

/// some global functions
class CGlobalChnCall
{
public:
	/** to compress for image BYTEs; reverse function is LoadPackBits
	 * @param pbBuf [out] output buffer, header ptr; may be NULL
	 * @param nBuf size of output buffer
	 * @param pbData [in] input buffer, 2 states only: 0 or not-0
	 * @param nData size of input buffer
	 * @retval int if pbBuf is NULL, return maximum BYTEs needed;
	 * if pbBuf is not NULL, return the actual BYTEs wrote.
	 */
	static int CreatePackBits(BYTE *pbBuf, int nBuf, const BYTE *pbData, int nData);
	/** to decompress for image BYTEs; reverse function of LoadPackBits
	 * @param pbBuf [out] output buffer, header ptr; may be NULL; output value will be 1 or 0
	 * @param nBuf size of output buffer
	 * @param pbData [in] input buffer
	 * @param nData size of input buffer
	 * @retval int if pbBuf is NULL, return maximum BYTEs needed;
	 * if pbBuf is not NULL, return the actual BYTEs wrote.
	 */
	static int LoadPackBits(BYTE *pbBuf, int nBuf, const BYTE *pbData, int nData);

public:
	/** to create pack/unpacked BYTEs to save points for a stroke
	 * @param lpPoint [in] points of a stroke
	 * @param nPoint count of lpPoint
	 * @param ppbData [out] output pack/unpacked BYTEs, should call delete[] to free
	 * @param nType type of creating method
	 * \arg 0 auto-checking
	 * \arg 1 no pack(compress)
	 * \arg 2 pack(the 1st point is in short; later point saved by offset in BYTEs)
	 * @retval int count of output BYTEs
	 */
	static int CreateBytes(const SPoint *lpPoint, int nPoint, BYTE **ppbData, int nType);
	/** to restore points of a stroke from array of short
	 * @param pPt [out] to output points of a stroke, in SPoint, may not be NULL
	 * @param nPt count of pPt
	 * @param pn [in] packed/unpacked BYTEs, in short
	 * @param bPack whether pn is packed or not
	 * @retval int how much SPoint outputted
	 */
	static int LoadPointsFromBytes(SPoint *pPt, int nPt, const short *pn, BOOL bPack);
	/** to get count of stroke; based on : coordinate of point should be no less than 0
	 * @param lpPoint [in] array in SPoint;
	 * denotes all strokes of a Chinese character; should not be NULL
	 * @param nPoint size of array
	 * @retval int count of stroke
	 */
	static int getStrokeCount(const SPoint *lpPoint, int nPoint);
	/** to pack array of SPoint(array points of a Chinese character) into BYTEs
	 * @param pbBuf [out] packed BYTEs; may be NULL, means to count how many BYTEs needed to call
	 * @param nBuf if pbBuf is not NULL, BYTEs of pbBuf; if pbBuf is NULL, ignored
	 * @param lpPoint [in] array of SPoint, segmented by (-1, y)
	 * @param nPoint count of input array
	 * @retval int count of BYTEs outputed(needed); 0, if fail.
	 */
	static int CreatePackBytes(BYTE *pbBuf, int nBuf, const SPoint *lpPoint, int nPoint);
	/** helper function for LoadPackBytes; to load(decompress) some BYTEs for one stroke only
	 * @param lpPoint [out] output points in SPoint
	 * @param nPoint count of lpPoint
	 * @param pbData [in] BYTEs to be read
	 * @param pnReadBytes [out] to output how many BYTEs being read for this stroke
	 * @retval int how many point being outputted
	 */
	static int LoadPackStrokeBytes(SPoint *lpPoint, int nPoint, const BYTE *pbData, int *pnReadBytes);
	/** to restore array of SPoint, reverse of CreatePackBytes
	 * @param lpPoint [out] output array of SPoint; may be NULL, to count how many SPoint needed to call
	 * @param nPoint count of lpPoint; if lpPoint is NULL, ignored
	 * @param pbData [in] packed BYTEs by CreatePackBytes
	 * @param nData BYTEs' count of pbData
	 * @retval int count of output SPoint
	 */
	static int LoadPackBytes(SPoint *lpPoint, int nPoint, const BYTE *pbData, int nData);

public:
#ifdef WIN32
	/** to save some writing data into a given file
	 * @param szFile [in] the given file to write
	 * @param wCode related unicode for this writing data
	 * @param dwRange LOWORD, maximum width(W); HIWORD, maximum height(H)
	 * @param pbOut [in] writing data, may not in W x H, for they may be compressed by CreatePackBits
	 * @param nOut BYTEs of pbOut, may be less than W x H
	 * @retval BOOL 1, if succeed; 0, if fail.
	 */
	static BOOL saveChnDraw(LPCTSTR szFile, wchar_t wCode, DWORD dwRange, const BYTE *pbOut, int nOut);
	/** to load writing data from a given file
	 * @param szFile [in] the given file to read/load
	 * @param pwCode [out] output related unicode
	 * @param pdwRange [out] output maximum width(LOWORD)/height(HIWORD)
	 * @param ppbOut [out] output writing data from the given file;
	 * should call freeBytes(.) to free output ptr.
	 * @retval int BYTEs of output data; -1, for file may not open; 0, for bad file format.
	 */
	static int loadChnDraw(LPCTSTR szFile, wchar_t *pwCode, DWORD *pdwRange, BYTE **ppbOut);
	/** to read related unicode from a given file
	 * @param pwCode [out] should not be NULL; caller should allocate at least 2 wchar_t to call
	 * @param szFile the given file to read
	 * @retval BOOL 0, if file not open or bad format; 1, if succeed.
	 */
	static BOOL loadChnCode(wchar_t *pwCode, LPCTSTR szFile);
	/** helper function for loadChnDraw(.)/createCtrlPoints(.)
	 * @param pbOut ptr to be destroyed
	 */
	static void freeBytes(BYTE *pbOut);
#endif	// WIN32

public:
	/** to create binary image by some control points
	 * @param ppbOut [out] output binary image ptr, row by row; should call freeBytes(.) to destroy
	 * @param dwRange LOWORD, maximum width; HIWORD, maximum height
	 * @param pPoint [in] given ptr of control points
	 * @param nPoint count of pPoint
	 * @retval int total BYTEs of output; 0, if fail.
	 */
	static int createCtrlPoints(BYTE **ppbOut, DWORD dwRange, const SPoint *pPoint, int nPoint);

public:
#ifdef _WIN32
	/** to query middle line, output array of SPoint
	 * @param pDB [in] class object, to access 'stroke.db'
	 * @param wCode unicode of Chn Code
	 * @param ppPoint [out] output array of SPoint;
	 * should be destroyed by delete[]
	 * @retval int count of output SPoint; -1, if argument error; 0, if fail.
	 */
	static int loadChnMidPoints(CStrokeDB *pDB, wchar_t wCode, SPoint **ppPoint);
	/** to query middle line, and contour line, output array of SPoint
	 * @param pDB [in] class object, to access 'stroke.db'
	 * @param wCode unicode of Chn Code
	 * @param nStrokeIndex 1-based stroke index
	 * @param ppPoint [out] output array of SPoint;
	 * should be destroyed by delete[];
	 * seperated by (-1, 0)
	 * @retval int count of output SPoint; -1, if argument error; 0, if fail.
	 */
	static int loadChnStrokePoints(CStrokeDB *pDB, wchar_t wCode, int nStrokeIndex, SPoint **ppPoint);
#endif	// _WIN32
};

#endif	// GLOBAL_CHN_RECOGNITION_2013_01_03_H
